package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.aliyun.GreenTextScan;
import com.heima.comment.dtos.CommentSaveDto;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentLike;
import com.heima.comment.pojos.CommentVo;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.constants.message.HotArticleConstants;
import com.heima.feigns.user.UserFeign;
import com.heima.model.behavior.pojos.UpdateArticleMess;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    UserFeign userFeign;
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    CommentHotService commentHotService;

    @Autowired
    GreenTextScan greenTextScan;
    @Autowired
    KafkaTemplate kafkaTemplate;

    /**
     * 添加评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //参数校验
        if (dto == null || dto.getArticleId() == null || StringUtils.isBlank(dto.getContent())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //获取登录人信息(apUser里面只有id)
        ApUser apUser = AppThreadLocalUtils.getUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //远程feign调用,根据id查询apUser完整属性
        apUser = userFeign.findUserById(apUser.getId());
        if (apUser == null || apUser.getStatus()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户不合法");
        }

        //阿里云内容反垃圾审核(block/review/pass)
        try {
            Map map = greenTextScan.greenTextScan(dto.getContent());
            if (map.get("suggestion").equals("block") || map.get("suggestion").equals("review")) {
                //审核失败
                log.error("阿里云审核: 评论中存在敏感词");
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "阿里云审核: 评论中存在敏感词");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //保存评论
        ApComment apComment = new ApComment();
        apComment.setAuthorId(apUser.getId());
        apComment.setAuthorName(apUser.getName());
        apComment.setImage(apUser.getImage());
        apComment.setContent(dto.getContent());
        apComment.setEntryId(dto.getArticleId());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType(0);
        apComment.setFlag(0);
        mongoTemplate.save(apComment);

        //*****kafka发送消息,实时计算热点分数******
        UpdateArticleMess mess = new UpdateArticleMess();
        mess.setArticleId(dto.getArticleId());
        mess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
        kafkaTemplate.send(HotArticleConstants.HOTARTICLE_SCORE_INPUT_TOPIC, JSON.toJSONString(mess));
        //****************
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 点赞评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //参数校验
        if (dto == null || dto.getCommentId() == null || dto.getOperation() > 1 || dto.getOperation() < 0) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //判断是否登录,获取登录人信息(apUser里面只有id)
        ApUser apUser = AppThreadLocalUtils.getUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //查询评论
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if (apComment == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //保存点赞/取消点赞
        if (dto.getOperation() == 0) {
            //判断是否重复点赞
            ApCommentLike apCommentLike = mongoTemplate.findOne(Query.query(Criteria.where("authorId").is(apUser.getId())
                    .and("commentId").is(dto.getCommentId())), ApCommentLike.class);
            if (apCommentLike != null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "已点赞");
            }
            //评论表点赞+1
            apComment.setLikes(apComment.getLikes() + 1);
            mongoTemplate.save(apComment);

            //*****计算热点评论*********
            if (apComment.getLikes() >= 5 && apComment.getFlag() == 0) {
                commentHotService.hotCommentExecutor(apComment.getEntryId(), apComment);
            }

            //点赞表执行保存点赞
            apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(apUser.getId());
            apCommentLike.setCommentId(apComment.getId());
            apCommentLike.setOperation(dto.getOperation());
            mongoTemplate.save(apCommentLike);
        } else {
            //评论表点赞-1
            apComment.setLikes(apComment.getLikes() <= 0 ? 0 : (apComment.getLikes() - 1));
            mongoTemplate.save(apComment);
            //删除点赞表
            mongoTemplate.remove(Query.query(Criteria.where("authorId").is(apUser.getId())
                    .and("commentId").is(dto.getCommentId())), ApCommentLike.class);
        }

        //封装返回
        Map<String, Object> map = new HashMap<>();
        map.put("likes", apComment.getLikes());
        return ResponseResult.okResult(map);
    }

    /**
     * 加载评论列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        //参数校验
        if (dto == null || dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (dto.getMinDate() == null) {
            dto.setMinDate(new Date());
        }
        List<ApComment> commentsList = new ArrayList<>();
        //*************热点评论列表***************
        if (dto.getIndex() == 1) {
            //获取热点评论列表
            commentsList = mongoTemplate.find(Query
                    .query(Criteria.where("entryId").is(dto.getArticleId())
                            .and("type").is(0)
                            .and("flag").is(1))
                    .with(Sort.by(Sort.Direction.DESC, "likes"))
                    .limit(5), ApComment.class);
            //如果存在热点评论(评论列表为热点(点赞排序)+非热点(创建时间排序))
            if (commentsList != null || commentsList.size() > 0) {
                int hsize = dto.getSize() - commentsList.size();
                List<ApComment> ptcomments = mongoTemplate.find(Query
                        .query(Criteria.where("entryId").is(dto.getArticleId())
                                .and("type").is(0)
                                .and("flag").is(0))
                        .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                        .limit(hsize), ApComment.class);
                commentsList.addAll(ptcomments);
            } else {
                //不存在热点评论,正常按创建时间排序
                commentsList = mongoTemplate.find(Query
                        .query(Criteria.where("entryId").is(dto.getArticleId())
                                .and("type").is(0)
                                .and("flag").is(0))
                        .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                        .limit(dto.getSize()), ApComment.class);
            }
        } else {
            //根据文章id查询文章评论列表
            commentsList = mongoTemplate.find(Query
                    .query(Criteria.where("entryId").is(dto.getArticleId())
                            .and("type").is(0)
                            .and("flag").is(0))
                    .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                    .limit(dto.getSize()), ApComment.class);
        }

        if (commentsList == null || commentsList.size() == 0) {
            return ResponseResult.okResult();
        }
        //*********************************************************

        //用户未登录直接返回列表
        ApUser apUser = AppThreadLocalUtils.getUser();
        if (apUser == null) {
            return ResponseResult.okResult(commentsList);
        }
        //用户登录,加载当前用户对评论点赞的列表
        List<CommentVo> commentVoList = new ArrayList<>();
        //获取评论id列表
        List<String> idList = commentsList.stream().map(x -> x.getId()).collect(Collectors.toList());

        //按照评论id查询点赞批量列表
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(Query.query(Criteria.where("commentId").in(idList)
                .and("authorId").is(apUser.getId())), ApCommentLike.class);

        // 遍历当前用户点赞列表 和当前评论列表
        if (commentsList != null && commentsList.size() > 0 && apCommentLikes != null && apCommentLikes.size() > 0) {
            for (ApComment apComment : commentsList) {
                CommentVo commentVo = new CommentVo();
                BeanUtils.copyProperties(apComment, commentVo);

                for (ApCommentLike apCommentLike : apCommentLikes) {
                    // 文章评论列表id 和 当前用户点赞评论列表id是否相等
                    if (apComment.getId().equals(apCommentLike.getCommentId())) {
                        commentVo.setOperation(0);
                    }
                }
                commentVoList.add(commentVo);
            }
            return ResponseResult.okResult(commentVoList);
        }
        return ResponseResult.okResult(commentsList);
    }
}
